using System.Collections.Generic;
using System.IO;
using System.Text;
using org.jawk.ext;
using System;

namespace org.jawk.backend
{
	/// <summary>The Jawk interpreter.</summary>
	/// <remarks>
	/// The Jawk interpreter.
	/// <p>
	/// It takes tuples constructed by the intermediate step
	/// and executes each tuple in accordance to their instruction semantics.
	/// The tuples correspond to the Awk script compiled by the parser.
	/// The interpreter consists of an instruction processor (interpreter),
	/// a runtime stack, and machinery to support the instruction set
	/// contained within the tuples.
	/// <p>
	/// The interpreter runs completely independent of the frontend/intermediate step.
	/// In fact, an intermediate file produced by Jawk is sufficient to
	/// execute on this interpreter.  The binding datastructure is
	/// the AwkParameters, which can contain options pertinent to
	/// the interpreter.  For example, the interpreter must know about
	/// the -v command line arguments, as well as the file/variable list
	/// parameters (ARGC/ARGV) after the script on the command line.
	/// However, if programmatic access to the AVM is required, meaningful
	/// AwkParameters are not required.
	/// <p>
	/// Semantic analysis has occurred prior to execution of the interpreter.
	/// Therefore, the interpreter throws AwkRuntimeExceptions upon most
	/// errors/conditions.  It can also throw a java.lang.Error if an
	/// interpreter error is encountered.
	/// </remarks>
	public class AVM : org.jawk.backend.IAwkInterpreter, org.jawk.jrt.IVariableManager
	{

		private org.jawk.backend.AVM.RuntimeStack runtime_stack = new org.jawk.backend.AVM.RuntimeStack
			();

		private org.jawk.util.IMyStack<object> operand_stack = new org.jawk.util.ArrayStackImpl
			<object>();

        private System.Collections.Generic.IList<object> arguments;

		private bool sorted_array_keys;

		private System.Collections.Generic.IDictionary<string, object> initial_variables;

		private string initial_fs_value;

		private bool trap_illegal_format_exceptions;

		private org.jawk.jrt.JRT jrt;

		private System.Collections.Generic.IDictionary<string, org.jawk.ext.IJawkExtension
			> extensions;

		// ONLY for DEFAULT_RS_REGEX
		// 16 slots by default
		// (could be a parameter)
		//private Deque<Object> operand_stack = new ArrayDeque<Object>(16);
		//private MyStack<Object> operand_stack = new LinkedListStackImpl<Object>();
		// stack methods
		//private Object pop() { return operand_stack.removeFirst(); }
		//private void push(Object o) { operand_stack.addLast(o); }
		private object Pop()
		{
			return operand_stack.Pop();
		}

		private void Push(object o)
		{
			operand_stack.Push(o);
		}

		private readonly org.jawk.util.AwkParameters parameters;

		/// <summary>Construct the interpreter.</summary>
		/// <remarks>
		/// Construct the interpreter.
		/// <p>
		/// Provided to allow programmatic construction of the interpreter
		/// outside of the framework which is used by Jawk.
		/// </remarks>
		public AVM()
		{
			parameters = null;
			arguments = new System.Collections.Generic.List<object>();
			sorted_array_keys = false;
			initial_variables = new System.Collections.Generic.Dictionary<string, object>();
			initial_fs_value = null;
			trap_illegal_format_exceptions = false;
			jrt = new org.jawk.jrt.JRT(this);
			// this = VariableManager
			this.extensions = new Dictionary<string, IJawkExtension>();
		}

		/// <summary>
		/// Construct the interpreter, accepting parameters which may have been
		/// set on the command-line arguments to the JVM.
		/// </summary>
		/// <remarks>
		/// Construct the interpreter, accepting parameters which may have been
		/// set on the command-line arguments to the JVM.
		/// </remarks>
		/// <param name="parameters">
		/// The parameters affecting the behavior of the
		/// interpreter.
		/// </param>
		/// <exception cref="System.ArgumentException"></exception>
		public AVM(org.jawk.util.AwkParameters parameters, System.Collections.Generic.IDictionary
			<string, org.jawk.ext.IJawkExtension> extensions)
		{
			if (parameters == null)
			{
				throw new System.ArgumentException("AwkParameters argument cannot be null");
			}
			this.parameters = parameters;
			arguments = parameters.name_value_filename_list;
			sorted_array_keys = parameters.sorted_array_keys;
			initial_variables = parameters.initial_variables;
			initial_fs_value = parameters.initial_fs_value;
			trap_illegal_format_exceptions = parameters.trap_illegal_format_exceptions;
			jrt = new org.jawk.jrt.JRT(this);
			// this = VariableManager
			this.extensions = extensions;
			foreach (org.jawk.ext.IJawkExtension ext in extensions.Values)
			{
				ext.Init(this, jrt);
			}
		}

		private int nf_offset = NULL_OFFSET;

		private int nr_offset = NULL_OFFSET;

		private int fnr_offset = NULL_OFFSET;

		private int fs_offset = NULL_OFFSET;

		private int rs_offset = NULL_OFFSET;

		private int ofs_offset = NULL_OFFSET;

		private int rstart_offset = NULL_OFFSET;

		private int rlength_offset = NULL_OFFSET;

		private int filename_offset = NULL_OFFSET;

		private int subsep_offset = NULL_OFFSET;

		private int convfmt_offset = NULL_OFFSET;

		private int ofmt_offset = NULL_OFFSET;

		private int environ_offset = NULL_OFFSET;

		private int argc_offset = NULL_OFFSET;

		private int argv_offset = NULL_OFFSET;

		private static readonly int ZERO = 0;

		private static readonly int ONE = 1;

		private System.Random random_number_generator;

		private int oldseed;

		private org.jawk.intermediate.IAddress exit_address = null;

		/// <summary>True if execution position is within an END block; false otherwise.</summary>
		/// <remarks>True if execution position is within an END block; false otherwise.</remarks>
		private bool within_end_blocks = false;

		private int exit_code = 0;

		/// <summary>Maps global variable names to their global array offsets.</summary>
		/// <remarks>
		/// Maps global variable names to their global array offsets.
		/// It is useful when passing variable assignments from the filelist
		/// portion of the command-line arguments.
		/// </remarks>
		private System.Collections.Generic.IDictionary<string, int> global_variable_offsets;

		/// <summary>
		/// Indicates whether the variable, by name, is a scalar
		/// or not.
		/// </summary>
		/// <remarks>
		/// Indicates whether the variable, by name, is a scalar
		/// or not.  If not, then it is an Associative Array.
		/// </remarks>
		private System.Collections.Generic.IDictionary<string, bool> global_variable_aarrays;

		private System.Collections.Generic.ICollection<string> function_names;

		// this = VariableManager
		// use a return code of 0 by default
		/// <summary>
		/// Traverse the tuples, executing their associated opcodes to provide
		/// an execution platform for Jawk scripts.
		/// </summary>
		/// <remarks>
		/// Traverse the tuples, executing their associated opcodes to provide
		/// an execution platform for Jawk scripts.
		/// </remarks>
		/// <param name="tuples">The tuples to interpret.</param>
		/// <returns>
		/// The return code (the value passed into the exit call).
		/// maxime
		/// </returns>
		public virtual int Interpret(org.jawk.intermediate.AwkTuples tuples)
		{
			System.Collections.Generic.IDictionary<string, System.Text.RegularExpressions.Regex> regexps =
                new System.Collections.Generic.Dictionary<string, System.Text.RegularExpressions.Regex>();
			System.Collections.Generic.IDictionary<int, org.jawk.jrt.PatternPair> pattern_pairs
				 = new System.Collections.Generic.Dictionary<int, org.jawk.jrt.PatternPair>();
			global_variable_offsets = tuples.GetGlobalVariableOffsetMap();
			global_variable_aarrays = tuples.GetGlobalVariableAarrayMap();
			function_names = tuples.GetFunctionNameSet();
			org.jawk.intermediate.IPositionForInterpretation position = (org.jawk.intermediate.IPositionForInterpretation
				)tuples.Top();
			try
			{
				while (!position.IsEOF())
				{
					//System_out.println("--> "+position);
					int opcode = position.Opcode();
					switch (opcode)
					{
						case org.jawk.intermediate.AwkTuples._PRINT_:
						{
							// switch on OPCODE
							// arg[0] = # of items to print on the stack
							// stack[0] = item 1
							// stack[1] = item 2
							// etc.
							int num_args = position.IntArg(0);
							PrintTo(System.Console.Out, num_args);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PRINT_TO_FILE_:
						{
							// arg[0] = # of items to print on the stack
							// arg[1] = true=append, false=overwrite
							// stack[0] = output filename
							// stack[1] = item 1
							// stack[2] = item 2
							// etc.
							int num_args = position.IntArg(0);
							bool append = position.BoolArg(1);
							string key = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
                            System.IO.TextWriter ps = null;
                            if (jrt.output_files.ContainsKey(key))
                            {
                                ps = jrt.output_files[key];
                            }
						    if (ps == null)
							{
								try
								{
									jrt.output_files[key] = ps = new StreamWriter(key,append);
								}
								catch (System.IO.IOException ioe)
								{
									// true = autoflush
									throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Cannot open " 
										+ key + " for writing: " + ioe);
								}
							}
							PrintTo(ps, num_args);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PRINT_TO_PIPE_:
						{
							// arg[0] = # of items to print on the stack
							// stack[0] = command to execute
							// stack[1] = item 1
							// stack[2] = item 2
							// etc.
							int num_args = position.IntArg(0);
							string cmd = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							System.IO.TextWriter ps = jrt.JrtSpawnForOutput(cmd);
							PrintTo(ps, num_args);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PRINTF_:
						{
							// arg[0] = # of items to print on the stack (includes format string)
							// stack[0] = format string
							// stack[1] = item 1
							// etc.
							int num_args = position.IntArg(0);
							PrintfTo(System.Console.Out, num_args);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PRINTF_TO_FILE_:
						{
							// arg[0] = # of items to print on the stack (includes format string)
							// arg[1] = true=append, false=overwrite
							// stack[0] = output filename
							// stack[1] = format string
							// stack[2] = item 1
							// etc.
							int num_args = position.IntArg(0);
							bool append = position.BoolArg(1);
							string key = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							System.IO.TextWriter ps = null;
                            if (jrt.output_files.ContainsKey(key))
                            {
                                ps = jrt.output_files[key];
                            }
							if (ps == null)
							{
								try
								{
									jrt.output_files[key] = ps = new StreamWriter(key,append);
								}
								catch (System.IO.IOException ioe)
								{
									// true = autoflush
									throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Cannot open " 
										+ key + " for writing: " + ioe);
								}
							}
							PrintfTo(ps, num_args);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PRINTF_TO_PIPE_:
						{
							// arg[0] = # of items to print on the stack (includes format string)
							// stack[0] = command to execute
							// stack[1] = format string
							// stack[2] = item 1
							// etc.
							int num_args = position.IntArg(0);
							string cmd = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							System.IO.TextWriter ps = jrt.JrtSpawnForOutput(cmd);
							PrintfTo(ps, num_args);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SPRINTF_:
						{
							// arg[0] = # of sprintf arguments
							// stack[0] = arg1 (format string)
							// stack[1] = arg2
							// etc.
							int num_args = position.IntArg(0);
							Push(SprintfFunction(num_args));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._LENGTH_:
						{
							// arg[0] = 0==use $0, otherwise, use the stack element
							// stack[0] = element to measure (only if arg[0] != 0)
							// print items from the top of the stack
							// # of items
							int num = position.IntArg(0);
							if (num == 0)
							{
								// display $0
								Push(jrt.JrtGetInputField(0).ToString().Length);
							}
							else
							{
								Push(Pop().ToString().Length);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PUSH_:
						{
							// arg[0] = constant to push onto the stack
							Push(position.Arg(0));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._POP_:
						{
							// stack[0] = item to pop from the stack
							Pop();
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._IFFALSE_:
						{
							// arg[0] = address to jump to if top of stack is false
							// stack[0] = item to check
							// if int, then check for 0
							// if double, then check for 0
							// if String, then check for "" or double value of "0"
							bool jump = !jrt.ToBoolean(Pop());
							if (jump)
							{
								position.Jump(position.AddressArg());
							}
							else
							{
								position.Next();
							}
							break;
						}

						case org.jawk.intermediate.AwkTuples._TO_NUMBER_:
						{
							// stack[0] = item to convert to a number
							// if int, then check for 0
							// if double, then check for 0
							// if String, then check for "" or double value of "0"
							bool val = jrt.ToBoolean(Pop());
							Push(val ? ONE : ZERO);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._IFTRUE_:
						{
							// arg[0] = address to jump to if top of stack is true
							// stack[0] = item to check
							// if int, then check for 0
							// if double, then check for 0
							// if String, then check for "" or double value of "0"
							bool jump = jrt.ToBoolean(Pop());
							if (jump)
							{
								position.Jump(position.AddressArg());
							}
							else
							{
								position.Next();
							}
							break;
						}

						case org.jawk.intermediate.AwkTuples._NOT_:
						{
							// stack[0] = item to logically negate
							// if int, then check for 0
							// if double, then check for 0
							// if String, then check for "" or double value of "0"
							object o = Pop();
							bool result;
							if (o is int)
							{
								result = ((int)o) != 0;
							}
							else
							{
								if (o is double)
								{
									result = ((double)o) != 0;
								}
								else
								{
									if (o is string)
									{
										result = (o.ToString().Length > 0);
									}
									else
									{
										throw new System.Exception("Unknown operand_stack type: " + o.GetType() + " for value "
											 + o);
									}
								}
							}
							if (result)
							{
								Push(0);
							}
							else
							{
								Push(1);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._NEGATE_:
						{
							// stack[0] = item to numerically negate
							double d = org.jawk.jrt.JRT.ToDouble(Pop());
							if (d == (int)d)
							{
								Push((int)-d);
							}
							else
							{
								Push(-d);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._GOTO_:
						{
							// arg[0] = address
							position.Jump(position.AddressArg());
							break;
						}

						case org.jawk.intermediate.AwkTuples._NOP_:
						{
							// do nothing, just advance the position
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CONCAT_:
						{
							// stack[0] = string1
							// stack[1] = string2
							string convfmt = GetCONVFMT().ToString();
							string s1 = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string s2 = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string result_string = s1 + s2;
							Push(result_string);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ASSIGN_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// stack[0] = value
							object value = Pop();
							bool is_global = position.BoolArg(1);
							Assign(position.IntArg(0), value, is_global, position);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ASSIGN_ARRAY_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// stack[0] = array index
							// stack[1] = value
							object arr_idx = Pop();
							object rhs = Pop();
							if (rhs == null)
							{
								rhs = BLANK;
							}
							int offset = position.IntArg(0);
							bool is_global = position.BoolArg(1);
							AssignArray(offset, arr_idx, rhs, is_global);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PLUS_EQ_ARRAY_:
						case org.jawk.intermediate.AwkTuples._MINUS_EQ_ARRAY_:
						case org.jawk.intermediate.AwkTuples._MULT_EQ_ARRAY_:
						case org.jawk.intermediate.AwkTuples._DIV_EQ_ARRAY_:
						case org.jawk.intermediate.AwkTuples._MOD_EQ_ARRAY_:
						case org.jawk.intermediate.AwkTuples._POW_EQ_ARRAY_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// stack[0] = array index
							// stack[1] = value
							object arr_idx = Pop();
							object rhs = Pop();
							if (rhs == null)
							{
								rhs = BLANK;
							}
							int offset = position.IntArg(0);
							bool is_global = position.BoolArg(1);
							double val = org.jawk.jrt.JRT.ToDouble(rhs);
							// from _DEREF_ARRAY_
							// stack[0] = AssocArray
							// stack[1] = array index
							object o1 = runtime_stack.GetVariable(offset, is_global);
							// map
							if (o1 == null)
							{
								runtime_stack.SetVariable(offset, o1 = new org.jawk.jrt.AssocArray(sorted_array_keys
									), is_global);
							}
							//else
							//	//assert o1 instanceof AssocArray;
							org.jawk.jrt.AssocArray array = (org.jawk.jrt.AssocArray)o1;
							object o = array.Get(arr_idx);
							//assert o != null;
							double orig_val = org.jawk.jrt.JRT.ToDouble(o);
							double new_val;
							switch (opcode)
							{
								case org.jawk.intermediate.AwkTuples._PLUS_EQ_ARRAY_:
								{
									new_val = orig_val + val;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MINUS_EQ_ARRAY_:
								{
									new_val = orig_val - val;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MULT_EQ_ARRAY_:
								{
									new_val = orig_val * val;
									break;
								}

								case org.jawk.intermediate.AwkTuples._DIV_EQ_ARRAY_:
								{
									new_val = orig_val / val;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MOD_EQ_ARRAY_:
								{
									new_val = orig_val % val;
									break;
								}

								case org.jawk.intermediate.AwkTuples._POW_EQ_ARRAY_:
								{
									new_val = System.Math.Pow(orig_val, val);
									break;
								}

								default:
								{
									throw new System.Exception("Invalid op code here: " + opcode);
								}
							}
							if (new_val == (int)new_val)
							{
								AssignArray(offset, arr_idx, (int)new_val, is_global);
							}
							else
							{
								AssignArray(offset, arr_idx, new_val, is_global);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ASSIGN_AS_INPUT_:
						{
							// stack[0] = value
							jrt.input_line = Pop().ToString();
							jrt.JrtParseFields();
							Push(jrt.input_line);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ASSIGN_AS_INPUT_FIELD_:
						{
							// stack[0] = field number
							// stack[1] = value
							object field_num_obj = Pop();
							int field_num;
							try
							{
                                field_num = Convert.ToInt32(field_num_obj);
							}
							catch
							{
								try
								{
									field_num = int.Parse(field_num_obj.ToString());
								}
								catch (FormatException)
								{
									field_num = 0;
								}
							}
							string value = Pop().ToString();
							Push(value);
							// leave the result on the stack
							if (field_num == 0)
							{
								jrt.input_line = value;
								jrt.JrtParseFields();
							}
							else
							{
								jrt.JrtSetInputField(value, field_num);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PLUS_EQ_:
						case org.jawk.intermediate.AwkTuples._MINUS_EQ_:
						case org.jawk.intermediate.AwkTuples._MULT_EQ_:
						case org.jawk.intermediate.AwkTuples._DIV_EQ_:
						case org.jawk.intermediate.AwkTuples._MOD_EQ_:
						case org.jawk.intermediate.AwkTuples._POW_EQ_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// stack[0] = value
							bool is_global = position.BoolArg(1);
							object o1 = runtime_stack.GetVariable(position.IntArg(0), is_global);
							if (o1 == null)
							{
								o1 = BLANK;
							}
							object o2 = Pop();
							double d1 = org.jawk.jrt.JRT.ToDouble(o1);
							double d2 = org.jawk.jrt.JRT.ToDouble(o2);
							double ans;
							switch (opcode)
							{
								case org.jawk.intermediate.AwkTuples._PLUS_EQ_:
								{
									ans = d1 + d2;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MINUS_EQ_:
								{
									ans = d1 - d2;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MULT_EQ_:
								{
									ans = d1 * d2;
									break;
								}

								case org.jawk.intermediate.AwkTuples._DIV_EQ_:
								{
									ans = d1 / d2;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MOD_EQ_:
								{
									ans = d1 % d2;
									break;
								}

								case org.jawk.intermediate.AwkTuples._POW_EQ_:
								{
									ans = System.Math.Pow(d1, d2);
									break;
								}

								default:
								{
									throw new System.Exception("Invalid opcode here: " + opcode);
								}
							}
							if (ans == (int)ans)
							{
								Push((int)ans);
								runtime_stack.SetVariable(position.IntArg(0), (int)ans, is_global);
							}
							else
							{
								Push(ans);
								runtime_stack.SetVariable(position.IntArg(0), ans, is_global);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._PLUS_EQ_INPUT_FIELD_:
						case org.jawk.intermediate.AwkTuples._MINUS_EQ_INPUT_FIELD_:
						case org.jawk.intermediate.AwkTuples._MULT_EQ_INPUT_FIELD_:
						case org.jawk.intermediate.AwkTuples._DIV_EQ_INPUT_FIELD_:
						case org.jawk.intermediate.AwkTuples._MOD_EQ_INPUT_FIELD_:
						case org.jawk.intermediate.AwkTuples._POW_EQ_INPUT_FIELD_:
						{
							// stack[0] = dollar_field_number
							// stack[1] = inc value
							// same code as _GET_INPUT_FIELD_:
							object o = Pop();
							int fieldnum;
							try
							{
                                fieldnum = Convert.ToInt32(o);
							}
							catch
							{
								try
								{
									fieldnum = Convert.ToInt32(double.Parse(o.ToString(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
								}
								catch (FormatException)
								{
									throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Field $(" + o.
										ToString() + ") is incorrect.");
								}
							}
							double incval = org.jawk.jrt.JRT.ToDouble(Pop());
							// except here, get the number, and add the incvalue
							object num_obj = jrt.JrtGetInputField(fieldnum);
							double num;
							switch (opcode)
							{
								case org.jawk.intermediate.AwkTuples._PLUS_EQ_INPUT_FIELD_:
								{
									num = org.jawk.jrt.JRT.ToDouble(num_obj) + incval;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MINUS_EQ_INPUT_FIELD_:
								{
									num = org.jawk.jrt.JRT.ToDouble(num_obj) - incval;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MULT_EQ_INPUT_FIELD_:
								{
									num = org.jawk.jrt.JRT.ToDouble(num_obj) * incval;
									break;
								}

								case org.jawk.intermediate.AwkTuples._DIV_EQ_INPUT_FIELD_:
								{
									num = org.jawk.jrt.JRT.ToDouble(num_obj) / incval;
									break;
								}

								case org.jawk.intermediate.AwkTuples._MOD_EQ_INPUT_FIELD_:
								{
									num = org.jawk.jrt.JRT.ToDouble(num_obj) % incval;
									break;
								}

								case org.jawk.intermediate.AwkTuples._POW_EQ_INPUT_FIELD_:
								{
									num = System.Math.Pow(org.jawk.jrt.JRT.ToDouble(num_obj), incval);
									break;
								}

								default:
								{
									throw new System.Exception("Invalid opcode here: " + opcode);
								}
							}
							string num_string;
							if (num == (int)num)
							{
                                num_string = ((int)num).ToString();
							}
							else
							{
								num_string = num.ToString();
							}
							// same code as _ASSIGN_AS_INPUT_FIELD_
							if (fieldnum == 0)
							{
								jrt.input_line = num_string.ToString();
								jrt.JrtParseFields();
							}
							else
							{
								jrt.JrtSetInputField(num_string, fieldnum);
							}
							// put the result value on the stack
							Push(num);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._INC_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							Inc(position.IntArg(0), position.BoolArg(1));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DEC_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							Dec(position.IntArg(0), position.BoolArg(1));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._INC_ARRAY_REF_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// stack[0] = array index
							bool is_global = position.BoolArg(1);
							object o1 = runtime_stack.GetVariable(position.IntArg(0), is_global);
							if (o1 == null || (o1 is string) && o1.Equals(BLANK))
							{
								runtime_stack.SetVariable(position.IntArg(0), o1 = new org.jawk.jrt.AssocArray(sorted_array_keys
									), is_global);
							}
							org.jawk.jrt.AssocArray aa = (org.jawk.jrt.AssocArray)o1;
							object key = Pop();
							object o = aa.Get(key);
							//assert o != null;
							double ans = org.jawk.jrt.JRT.ToDouble(o) + 1;
							if (ans == (int)ans)
							{
								aa.Put(key, (int)ans);
							}
							else
							{
								aa.Put(key, ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DEC_ARRAY_REF_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// stack[0] = array index
							bool is_global = position.BoolArg(1);
							object o1 = runtime_stack.GetVariable(position.IntArg(0), is_global);
							if (o1 == null || (o1 is string) && o1.Equals(BLANK))
							{
								runtime_stack.SetVariable(position.IntArg(0), o1 = new org.jawk.jrt.AssocArray(sorted_array_keys
									), is_global);
							}
							org.jawk.jrt.AssocArray aa = (org.jawk.jrt.AssocArray)o1;
							object key = Pop();
							object o = aa.Get(key);
							//assert o != null;
							double ans = org.jawk.jrt.JRT.ToDouble(o) - 1;
							if (ans == (int)ans)
							{
								aa.Put(key, (int)ans);
							}
							else
							{
								aa.Put(key, ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._INC_DOLLAR_REF_:
						{
							// stack[0] = dollar index (field number)
							// same code as _GET_INPUT_FIELD_:
							object o = Pop();
							int fieldnum;
							try
							{
								fieldnum = Convert.ToInt32(o);
							}
							catch
							{
								try
								{
									fieldnum = (int)double.Parse(o.ToString(),System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
								}
								catch (FormatException)
								{
									throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Field $(" + o.
										ToString() + ") is incorrect.");
								}
							}
							// except here, get the number, and add one
							//push(avmGetInputField(fieldnum));
							object num_obj = jrt.JrtGetInputField(fieldnum);
							double num = org.jawk.jrt.JRT.ToDouble(num_obj) + 1;
							string num_string;
							if (num == (int)num)
							{
                                num_string = ((int)num).ToString();
							}
							else
							{
                                num_string = num.ToString();
							}
							// same code as _ASSIGN_AS_INPUT_FIELD_
							if (fieldnum == 0)
							{
								jrt.input_line = num_string.ToString();
								jrt.JrtParseFields();
							}
							else
							{
								jrt.JrtSetInputField(num_string, fieldnum);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DEC_DOLLAR_REF_:
						{
							// stack[0] = dollar index (field number)
							// same code as _GET_INPUT_FIELD_:
							object o = Pop();
							int fieldnum;
							try
							{
								fieldnum = Convert.ToInt32(o);
							}
							catch
							{
								try
								{
									fieldnum = (int)double.Parse(o.ToString(),System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
								}
								catch (FormatException)
								{
									throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Field $(" + o.
										ToString() + ") is incorrect.");
								}
							}
							// except here, get the number, and add one
							//push(avmGetInputField(fieldnum));
							object num_obj = jrt.JrtGetInputField(fieldnum);
							double num = org.jawk.jrt.JRT.ToDouble(num_obj) - 1;
							string num_string;
							if (num == (int)num)
							{
								num_string = ((int)num).ToString();
							}
							else
							{
								num_string = num.ToString();
							}
							// same code as _ASSIGN_AS_INPUT_FIELD_
							if (fieldnum == 0)
							{
								jrt.input_line = num_string.ToString();
								jrt.JrtParseFields();
							}
							else
							{
								jrt.JrtSetInputField(num_string, fieldnum);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DEREFERENCE_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							bool is_global = position.BoolArg(2);
							object o = runtime_stack.GetVariable(position.IntArg(0), is_global);
							if (o == null)
							{
								if (position.BoolArg(1))
								{
									// is_array
									Push(runtime_stack.SetVariable(position.IntArg(0), new org.jawk.jrt.AssocArray(sorted_array_keys
										), is_global));
								}
								else
								{
									Push(runtime_stack.SetVariable(position.IntArg(0), BLANK, is_global));
								}
							}
							else
							{
								Push(o);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DEREF_ARRAY_:
						{
							// stack[0] = AssocArray
							// stack[1] = array index
							object o1 = Pop();
							// map
							object o2 = Pop();
							// idx
							if (!(o1 is org.jawk.jrt.AssocArray))
							{
								throw new org.jawk.jrt.AwkRuntimeException("Attempting to index a non-associative-array."
									);
							}
							org.jawk.jrt.AssocArray array = (org.jawk.jrt.AssocArray)o1;
							object o = array.Get(o2);
							//assert o != null;
							Push(o);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SRAND_:
						{
							// arg[0] = num_args (where 0 = no args, anything else = one argument)
							// stack[0] = seed (only if num_args != 0)
							int numargs = position.IntArg(0);
							int seed;
							if (numargs == 0)
							{
								// use the time of day for the seed
								seed = org.jawk.jrt.JRT.TimeSeed();
							}
							else
							{
								object o = Pop();
								if (o is double)
								{
									seed = (int)((double)o);
								}
								else
								{
									if (o is int)
									{
										seed = ((int)o);
									}
									else
									{
										try
										{
											seed = int.Parse(o.ToString());
										}
										catch (FormatException)
										{
											seed = 0;
										}
									}
								}
							}
							random_number_generator = new System.Random(seed);
							Push(oldseed);
							oldseed = seed;
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._RAND_:
						{
							if (random_number_generator == null)
							{
								int seed = org.jawk.jrt.JRT.TimeSeed();
								random_number_generator = new System.Random(seed);
								oldseed = seed;
							}
							Push(random_number_generator.NextDouble());
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._INTFUNC_:
						case org.jawk.intermediate.AwkTuples._CAST_INT_:
						{
							// stack[0] = arg to int() function
							Push((int)org.jawk.jrt.JRT.ToDouble(Pop()));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SQRT_:
						{
							// stack[0] = arg to sqrt() function
							Push(System.Math.Sqrt(org.jawk.jrt.JRT.ToDouble(Pop())));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._LOG_:
						{
							// stack[0] = arg to log() function
							Push(System.Math.Log(org.jawk.jrt.JRT.ToDouble(Pop())));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._EXP_:
						{
							// stack[0] = arg to exp() function
							Push(System.Math.Exp(org.jawk.jrt.JRT.ToDouble(Pop())));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SIN_:
						{
							// stack[0] = arg to sin() function
							Push(System.Math.Sin(org.jawk.jrt.JRT.ToDouble(Pop())));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._COS_:
						{
							// stack[0] = arg to cos() function
							Push(System.Math.Cos(org.jawk.jrt.JRT.ToDouble(Pop())));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ATAN2_:
						{
							// stack[0] = 1st arg to atan2() function
							// stack[1] = 2nd arg to atan2() function
							double d1 = org.jawk.jrt.JRT.ToDouble(Pop());
							double d2 = org.jawk.jrt.JRT.ToDouble(Pop());
							Push(System.Math.Atan2(d1, d2));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._MATCH_:
						{
							// stack[0] = 1st arg to match() function
							// stack[1] = 2nd arg to match() function
							string convfmt = GetCONVFMT().ToString();
							string s = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string ere = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
                            System.Text.RegularExpressions.Regex pattern = new System.Text.RegularExpressions.Regex(ere);
							
							bool result = pattern.IsMatch(s);
							if (result)
							{
                                System.Text.RegularExpressions.Match match = pattern.Match(s);
								Assign(rstart_offset, match.Index + 1, true, position);
								Assign(rlength_offset, match.Length, true, position);
								Pop();
							}
							else
							{
								// end up with RSTART on the stack
								Assign(rstart_offset, ZERO, true, position);
								Assign(rlength_offset, -1, true, position);
								Pop();
							}
							// end up with RSTART on the stack
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._INDEX_:
						{
							// stack[0] = 1st arg to index() function
							// stack[1] = 2nd arg to index() function
							string convfmt = GetCONVFMT().ToString();
							string s1 = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string s2 = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							Push(s1.IndexOf(s2) + 1);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SUB_FOR_DOLLAR_0_:
						{
							// arg[0] = is_global
							// stack[0] = ere
							// stack[1] = replacement string
							bool is_gsub = position.BoolArg(0);
							// top-of-stack = ere
							// next = repl
							// (use $0 as orig)
							string convfmt = GetCONVFMT().ToString();
							string ere = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string repl = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string orig = org.jawk.jrt.JRT.ToAwkString(jrt.JrtGetInputField(0), convfmt);
							string newstring;
							if (is_gsub)
							{
								newstring = ReplaceAll(orig, ere, repl);
							}
							else
							{
								newstring = ReplaceFirst(orig, ere, repl);
							}
							// assign it to "$0"
							jrt.input_line = newstring;
							jrt.JrtParseFields();
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SUB_FOR_DOLLAR_REFERENCE_:
						{
							// arg[0] = is_global
							// stack[0] = field num
							// stack[1] = ere
							// stack[2] = replacement string
							// stack[3] = original field value
							bool is_gsub = position.BoolArg(0);
							// top-of-stack = ere
							// next = repl
							// (use $field_num as orig)
							int field_num = (int)org.jawk.jrt.JRT.ToDouble(Pop());
							// discovered it already existed on the stack (see below)
							//String orig = toAwkString(avmGetInputField(field_num));
							string convfmt = GetCONVFMT().ToString();
							string ere = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string repl = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string orig = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string newstring;
							if (is_gsub)
							{
								newstring = ReplaceAll(orig, ere, repl);
							}
							else
							{
								newstring = ReplaceFirst(orig, ere, repl);
							}
							// assign it to "$0"
							if (field_num == 0)
							{
								jrt.input_line = newstring;
								jrt.JrtParseFields();
							}
							else
							{
								jrt.JrtSetInputField(newstring, field_num);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SUB_FOR_VARIABLE_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// arg[2] = is_gsub
							// stack[0] = ere
							// stack[1] = replacement string
							// stack[2] = original variable value
							int offset = position.IntArg(0);
							bool is_global = position.BoolArg(1);
							bool is_gsub = position.BoolArg(2);
							// top-of-stack = ere
							// next = repl
							// next = orig
							string convfmt = GetCONVFMT().ToString();
							string ere = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string repl = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string orig = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string newstring;
							if (is_gsub)
							{
								newstring = ReplaceAll(orig, ere, repl);
							}
							else
							{
								newstring = ReplaceFirst(orig, ere, repl);
							}
							// assign it to "offset/global"
							Assign(offset, newstring, is_global, position);
							Pop();
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SUB_FOR_ARRAY_REFERENCE_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// arg[2] = is_gsub
							// stack[0] = array index
							// stack[1] = ere
							// stack[2] = replacement string
							// stack[3] = original variable value
							// ARRAY reference offset/is_global
							int offset = position.IntArg(0);
							bool is_global = position.BoolArg(1);
							bool is_gsub = position.BoolArg(2);
							// top-of-stack = array index
							// next = ere
							// next = repl
							// next = orig
							object arr_idx = Pop();
							string convfmt = GetCONVFMT().ToString();
							string ere = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string repl = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string orig = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							string newstring;
							if (is_gsub)
							{
								newstring = ReplaceAll(orig, ere, repl);
							}
							else
							{
								newstring = ReplaceFirst(orig, ere, repl);
							}
							// assign it to "offset/arr_idx/global"
							AssignArray(offset, arr_idx, newstring, is_global);
							Pop();
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SPLIT_:
						{
							// arg[0] = num args
							// stack[0] = string
							// stack[1] = array
							// stack[2] = field_sep (only if num args == 3)
							int numargs = position.IntArg(0);
							string convfmt = GetCONVFMT().ToString();
							string s = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							object o = Pop();
							if (!(o is org.jawk.jrt.AssocArray))
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), o + " is not an array."
									);
							}
							string fs_string;
							if (numargs == 2)
							{
								fs_string = org.jawk.jrt.JRT.ToAwkString(GetFS(), convfmt);
							}
							else
							{
								if (numargs == 3)
								{
									fs_string = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
								}
								else
								{
									throw new System.Exception("Invalid # of args.  split() tequires 2 or 3.  Got: " 
										+ numargs);
								}
							}
							java.util.IEnumeration<object> tokenizer;
							if (numargs == 2 && fs_string.Equals(" "))
							{
								tokenizer = new java.util.StringTokenizer(s);
							}
							else
							{
								if (numargs == 2 && fs_string.Length == 1)
								{
									tokenizer = new org.jawk.jrt.SingleCharacterTokenizer(s, fs_string[0]);
								}
								else
								{
									if (numargs == 2 && fs_string.Equals(BLANK))
									{
										tokenizer = new org.jawk.jrt.CharacterTokenizer(s);
									}
									else
									{
										tokenizer = new org.jawk.jrt.RegexTokenizer(s, fs_string);
									}
								}
							}
							org.jawk.jrt.AssocArray assoc_array = (org.jawk.jrt.AssocArray)o;
							assoc_array.Clear();
							int cnt = 0;
							while (tokenizer.HasMoreElements())
							{
								assoc_array.Put(++cnt, tokenizer.NextElement());
							}
							Push(cnt);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SUBSTR_:
						{
							// arg[0] = num args
							// stack[0] = string
							// stack[1] = start pos
							// stack[2] = end pos (only if num args == 3)
							int numargs = position.IntArg(0);
							string s = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							int m = (int)org.jawk.jrt.JRT.ToDouble(Pop());
							if (m <= 0)
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "2nd arg to substr must be a positive integer"
									);
							}
							if (m > s.Length)
							{
								if (numargs == 2)
								{
								}
								else
								{
									if (numargs == 3)
									{
										Pop();
									}
									else
									{
										throw new System.Exception("numargs for _SUBSTR_ must be 2 or 3.  It is " + numargs
											);
									}
								}
								Push(BLANK);
							}
							else
							{
								if (numargs == 2)
								{
									Push(s.Substring(m - 1));
								}
								else
								{
									if (numargs == 3)
									{
										int n = (int)org.jawk.jrt.JRT.ToDouble(Pop());
										if (n < 0)
										{
											throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "3rd arg to substr must be a non-negative integer"
												);
										}
										if (m - 1 + n > s.Length)
										{
                                            Push(s.Substring(m - 1));
										}
										else
										{
                                            Push(s.Substring(m - 1, n));
										}
									}
									else
									{
										throw new System.Exception("numargs for _SUBSTR_ must be 2 or 3.  It is " + numargs
											);
									}
								}
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._TOLOWER_:
						{
							// stack[0] = string
							Push(org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString()).ToLower());
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._TOUPPER_:
						{
							// stack[0] = string
							Push(org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString()).ToUpper());
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SYSTEM_:
						{
							// stack[0] = command string
							string s = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							Push(org.jawk.jrt.JRT.JrtSystem(s));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SWAP_:
						{
							// stack[0] = item1
							// stack[1] = item2
							SwapOnStack();
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CMP_EQ_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							Push(org.jawk.jrt.JRT.Compare2(o1, o2, 0) ? ONE : ZERO);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CMP_LT_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							Push(org.jawk.jrt.JRT.Compare2(o1, o2, -1) ? ONE : ZERO);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CMP_GT_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							Push(org.jawk.jrt.JRT.Compare2(o1, o2, 1) ? ONE : ZERO);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._MATCHES_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							// use o1's string value
							string s = o1.ToString();
							// assume o2 is a regexp
							if (o2 is System.Text.RegularExpressions.Regex)
							{
                                System.Text.RegularExpressions.Regex p = (System.Text.RegularExpressions.Regex)o2;
								// m.matches() matches the ENTIRE string
								// m.find() is more appropriate
								bool result = p.IsMatch(s);
								Push(result ? 1 : 0);
							}
							else
							{
								string r = org.jawk.jrt.JRT.ToAwkString(o2, GetCONVFMT().ToString());
                                bool result = new System.Text.RegularExpressions.Regex(r).IsMatch(s);
								Push(result ? 1 : 0);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SLEEP_:
						{
							// arg[0] = num_args
							// if (num_args==1)
							// 	stack[0] = # of seconds
							// else
							// 	nothing on the stack
							//int seconds = (int) JRT.toDouble(pop());
							int seconds;
							int numargs = position.IntArg(0);
							if (numargs == 0)
							{
								seconds = 1;
							}
							else
							{
								seconds = (int)org.jawk.jrt.JRT.ToDouble(Pop());
							}
							try
							{
								System.Threading.Thread.Sleep(seconds * 1000);
							}
							catch (System.Exception ie)
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Caught exception while waiting for process exit: "
									 + ie);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DUMP_:
						{
							// arg[0] = num_args
							// if (num_args==0)
							// 	all Jawk global variables
							// else
							// 	args are assoc arrays to display
							//int seconds = (int) JRT.toDouble(pop());
							int numargs = position.IntArg(0);
							org.jawk.jrt.AssocArray[] aa_array;
							if (numargs == 0)
							{
								aa_array = null;
							}
							else
							{
								aa_array = new org.jawk.jrt.AssocArray[numargs];
								for (int i = 0; i < numargs; ++i)
								{
									aa_array[i] = (org.jawk.jrt.AssocArray)Pop();
								}
							}
							AvmDump(aa_array);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ADD_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							double d1 = org.jawk.jrt.JRT.ToDouble(o1);
							double d2 = org.jawk.jrt.JRT.ToDouble(o2);
							double ans = d1 + d2;
							if (ans == (int)ans)
							{
								Push((int)ans);
							}
							else
							{
								Push(ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SUBTRACT_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							double d1 = org.jawk.jrt.JRT.ToDouble(o1);
							double d2 = org.jawk.jrt.JRT.ToDouble(o2);
							double ans = d1 - d2;
							if (ans == (int)ans)
							{
								Push((int)ans);
							}
							else
							{
								Push(ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._MULTIPLY_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							double d1 = org.jawk.jrt.JRT.ToDouble(o1);
							double d2 = org.jawk.jrt.JRT.ToDouble(o2);
							double ans = d1 * d2;
							if (ans == (int)ans)
							{
								Push((int)ans);
							}
							else
							{
								Push(ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DIVIDE_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							double d1 = org.jawk.jrt.JRT.ToDouble(o1);
							double d2 = org.jawk.jrt.JRT.ToDouble(o2);
							double ans = d1 / d2;
							if (ans == (int)ans)
							{
								Push((int)ans);
							}
							else
							{
								Push(ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._MOD_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							double d1 = org.jawk.jrt.JRT.ToDouble(o1);
							double d2 = org.jawk.jrt.JRT.ToDouble(o2);
							double ans = d1 % d2;
							if (ans == (int)ans)
							{
								Push((int)ans);
							}
							else
							{
								Push(ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._POW_:
						{
							// stack[0] = item1
							// stack[1] = item2
							object o1 = Pop();
							object o2 = Pop();
							double d1 = org.jawk.jrt.JRT.ToDouble(o1);
							double d2 = org.jawk.jrt.JRT.ToDouble(o2);
							double ans = System.Math.Pow(d1, d2);
							if (ans == (int)ans)
							{
								Push((int)ans);
							}
							else
							{
								Push(ans);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DUP_:
						{
							// stack[0] = top of stack item
							object o = Pop();
							Push(o);
							Push(o);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._KEYLIST_:
						{
							// stack[0] = AssocArray
							object o = Pop();
							//assert o != null;
							if (!(o is org.jawk.jrt.AssocArray))
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Cannot get a keylist (via 'in') of a non associative array.  arg = "
									 + o.GetType() + ", " + o);
							}
							org.jawk.jrt.AssocArray aa = (org.jawk.jrt.AssocArray)o;
							Push(new org.jawk.jrt.KeyListImpl(aa.KeySet()));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._IS_EMPTY_KEYLIST_:
						{
							// arg[0] = address
							// stack[0] = KeyList
							object o = Pop();
							if (o == null || !(o is org.jawk.jrt.IKeyList))
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Cannot get a keylist (via 'in') of a non associative array.  arg = "
									 + o.GetType() + ", " + o);
							}
							org.jawk.jrt.IKeyList keylist = (org.jawk.jrt.IKeyList)o;
							if (keylist.Size() == 0)
							{
								position.Jump(position.AddressArg());
							}
							else
							{
								position.Next();
							}
							break;
						}

						case org.jawk.intermediate.AwkTuples._GET_FIRST_AND_REMOVE_FROM_KEYLIST_:
						{
							// stack[0] = KeyList
							object o = Pop();
							if (o == null || !(o is org.jawk.jrt.IKeyList))
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Cannot get a keylist (via 'in') of a non associative array.  arg = "
									 + o.GetType() + ", " + o);
							}
							// pop off and return the head of the key set
							org.jawk.jrt.IKeyList keylist = (org.jawk.jrt.IKeyList)o;
							//assert keylist.size() > 0;
							Push(keylist.GetFirstAndRemove());
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CHECK_CLASS_:
						{
							// arg[0] = class object
							// stack[0] = item to check
							object o = Pop();
							if (!(position.ClassArg().IsInstanceOfType(o)))
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Verification failed.  Top-of-stack = "
									 + o.GetType() + " isn't an instance of " + position.ClassArg());
							}
							Push(o);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CONSUME_INPUT_:
						{
							// arg[0] = address
							// false = do NOT put result on stack...
							// instead, put it in field vars ($0, $1, ...)
							try
							{
								if (AvmConsumeInput(false))
								{
									position.Next();
								}
								else
								{
									position.Jump(position.AddressArg());
								}
							}
							catch (System.IO.IOException ioe)
							{
								//assert false : "Should not throw io exception here.  ioe = "+ioe;
								throw new System.Exception("Should not throw io exception here.  ioe = " + ioe);
							}
							break;
						}

						case org.jawk.intermediate.AwkTuples._GETLINE_INPUT_:
						{
							AvmConsumeInputForGetline();
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._USE_AS_FILE_INPUT_:
						{
							// stack[0] = filename
							string s = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							AvmConsumeFileInputForGetline(s);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._USE_AS_COMMAND_INPUT_:
						{
							// stack[0] = command line
							string s = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							AvmConsumeCommandInputForGetline(s);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._NF_OFFSET_:
						{
							// stack[0] = offset
							nf_offset = position.IntArg(0);
							//assert nf_offset != NULL_OFFSET;
							Assign(nf_offset, 0, true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._NR_OFFSET_:
						{
							// stack[0] = offset
							nr_offset = position.IntArg(0);
							//assert nr_offset != NULL_OFFSET;
							Assign(nr_offset, 0, true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._FNR_OFFSET_:
						{
							// stack[0] = offset
							fnr_offset = position.IntArg(0);
							//assert fnr_offset != NULL_OFFSET;
							Assign(fnr_offset, 0, true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._FS_OFFSET_:
						{
							// stack[0] = offset
							fs_offset = position.IntArg(0);
							//assert fs_offset != NULL_OFFSET;
							if (initial_fs_value == null)
							{
								Assign(fs_offset, " ", true, position);
							}
							else
							{
								Assign(fs_offset, initial_fs_value, true, position);
							}
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._RS_OFFSET_:
						{
							// stack[0] = offset
							rs_offset = position.IntArg(0);
							//assert rs_offset != NULL_OFFSET;
							Assign(rs_offset, org.jawk.jrt.JRT.DEFAULT_RS_REGEX, true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._OFS_OFFSET_:
						{
							// stack[0] = offset
							ofs_offset = position.IntArg(0);
							//assert ofs_offset != NULL_OFFSET;
							Assign(ofs_offset, " ", true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._RSTART_OFFSET_:
						{
							// stack[0] = offset
							rstart_offset = position.IntArg(0);
							//assert rstart_offset != NULL_OFFSET;
							Assign(rstart_offset, string.Empty, true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._RLENGTH_OFFSET_:
						{
							// stack[0] = offset
							rlength_offset = position.IntArg(0);
							//assert rlength_offset != NULL_OFFSET;
							Assign(rlength_offset, string.Empty, true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._FILENAME_OFFSET_:
						{
							// stack[0] = offset
							filename_offset = position.IntArg(0);
							//assert filename_offset != NULL_OFFSET;
							Assign(filename_offset, string.Empty, true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SUBSEP_OFFSET_:
						{
							// stack[0] = offset
							subsep_offset = position.IntArg(0);
							//assert subsep_offset != NULL_OFFSET;
							Assign(subsep_offset, new string(new char[] { (char)28 }), true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CONVFMT_OFFSET_:
						{
							// stack[0] = offset
							convfmt_offset = position.IntArg(0);
							//assert convfmt_offset != NULL_OFFSET;
							Assign(convfmt_offset, "0.000000", true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._OFMT_OFFSET_:
						{
							// stack[0] = offset
							ofmt_offset = position.IntArg(0);
							//assert ofmt_offset != NULL_OFFSET;
							Assign(ofmt_offset, "0.000000", true, position);
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ENVIRON_OFFSET_:
						{
							// stack[0] = offset
							//// assignArray(offset, arr_idx, newstring, is_global);
							environ_offset = position.IntArg(0);
							//assert environ_offset != NULL_OFFSET;
							// set the initial variables

                            System.Collections.IDictionary env = Environment.GetEnvironmentVariables();
								
							foreach (string key in env.Keys)
							{
								AssignArray(environ_offset, key, env[key], true);
								Pop();
							}
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ARGC_OFFSET_:
						{
							// stack[0] = offset
							argc_offset = position.IntArg(0);
							//assert argc_offset != NULL_OFFSET;
							//assign(argc_offset, arguments.size(), true, position);	// true = global
							// +1 to include the "java Awk" (ARGV[0])
							Assign(argc_offset, arguments.Count + 1, true, position);
							// true = global
							Pop();
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._ARGV_OFFSET_:
						{
							// stack[0] = offset
							argv_offset = position.IntArg(0);
							//assert argv_offset != NULL_OFFSET;
							// consume argv (looping from 1 to argc)
							int argc = (int)org.jawk.jrt.JRT.ToDouble(runtime_stack.GetVariable(argc_offset, 
								true));
							// true = global
							AssignArray(argv_offset, 0, "java Awk", true);
							Pop();
							for (int i = 1; i < argc; i++)
							{
								//assignArray(argv_offset, i+1, arguments.get(i), true);
								AssignArray(argv_offset, i, arguments[i - 1], true);
								Pop();
							}
							// clean up the stack after the assignment
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._GET_INPUT_FIELD_:
						{
							// stack[0] = field number
							object o = Pop();
							int fieldnum;
							try
							{
								fieldnum = Convert.ToInt32(o);
							}
							catch
							{
								try
								{
                                    fieldnum = (int)double.Parse(o.ToString(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
								}
								catch (FormatException)
								{
									throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "Field $(" + o.
										ToString() + ") is incorrect.");
								}
							}
							Push(jrt.JrtGetInputField(fieldnum));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._APPLY_RS_:
						{
							//assert rs_offset != NULL_OFFSET;
							object rs_obj = runtime_stack.GetVariable(rs_offset, true);
							// true = global
							if (jrt.pr != null)
							{
								jrt.pr.RS(rs_obj.ToString());
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CALL_FUNCTION_:
						{
							// arg[0] = function address
							// arg[1] = function name
							// arg[2] = # of formal parameters
							// arg[3] = # of actual parameters
							// stack[0] = first actual parameter
							// stack[1] = second actual parameter
							// etc.
							org.jawk.intermediate.IAddress func_addr = position.AddressArg();
							string func_name = position.Arg(1).ToString();
							int num_formal_params = position.IntArg(2);
							int num_actual_params = position.IntArg(3);
							//assert num_formal_params >= num_actual_params;
							runtime_stack.PushFrame(num_formal_params, position.Current());
							for (int i = 0; i < num_actual_params; i++)
							{
								runtime_stack.SetVariable(i, Pop(), false);
							}
							// false = local
							position.Jump(func_addr);
							//position.next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._FUNCTION_:
						{
							// important for compilation,
							// not needed for interpretation
							// arg[0] = function name
							// arg[1] = # of formal parameters
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SET_RETURN_RESULT_:
						{
							// stack[0] = return result
							runtime_stack.SetReturnValue(Pop());
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._RETURN_FROM_FUNCTION_:
						{
							position.Jump(runtime_stack.PopFrame());
							Push(runtime_stack.GetReturnValue());
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SET_NUM_GLOBALS_:
						{
							// arg[0] = # of globals
							//assert position.intArg(0) == global_variable_offsets.size();
							runtime_stack.SetNumGlobals(position.IntArg(0));
							// now that we have the global variable size,
							// we can allocate the initial variables
							// assign -v variables (from initial_variables container)
							foreach (string key in initial_variables.Keys)
							{
								if (function_names.Contains(key))
								{
									throw new System.ArgumentException("Cannot assign a scalar to a function name (" + key + ").");
								}
								
								if (global_variable_aarrays.ContainsKey(key))
								{
                                    bool aarray_obj = global_variable_aarrays[key];
                                    int offset_obj = global_variable_offsets[key];
									//assert aarray_obj != null;
									if (aarray_obj)
									{
										throw new System.ArgumentException("Cannot assign a scalar to a non-scalar variable ("
											 + key + ").");
									}
									else
									{
										object obj = initial_variables[key];
										runtime_stack.SetFilelistVariable(offset_obj, obj);
									}
								}
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CLOSE_:
						{
							// stack[0] = file or command line to close
							string s = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							Push(jrt.JrtClose(s));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._APPLY_SUBSEP_:
						{
							// arg[0] = # of elements for SUBSEP application
							// stack[0] = first element
							// stack[1] = second element
							// etc.
							int count = position.IntArg(0);
							//assert count>=1;
							string s;
							string convfmt = GetCONVFMT().ToString();
							if (count == 1)
							{
								s = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
							}
							else
							{
								System.Text.StringBuilder sb = new System.Text.StringBuilder();
								sb.Append(org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt));
								string subsep = org.jawk.jrt.JRT.ToAwkString(runtime_stack.GetVariable(subsep_offset
									, true), convfmt);
								for (int i = 1; i < count; i++)
								{
									sb.Insert(0, subsep);
									sb.Insert(0, org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt));
								}
								Push(sb.ToString());
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DELETE_ARRAY_ELEMENT_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// stack[0] = array index
							int offset = position.IntArg(0);
							bool is_global = position.BoolArg(1);
							org.jawk.jrt.AssocArray aa = (org.jawk.jrt.AssocArray)runtime_stack.GetVariable(offset
								, is_global);
							object key = Pop();
							if (aa != null)
							{
								aa.Remove(key);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._DELETE_ARRAY_:
						{
							// arg[0] = offset
							// arg[1] = is_global
							// (nothing on the stack)
							int offset = position.IntArg(0);
							bool is_global = position.BoolArg(1);
							runtime_stack.RemoveVariable(offset, is_global);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SET_EXIT_ADDRESS_:
						{
							// arg[0] = exit address
							exit_address = position.AddressArg();
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._SET_WITHIN_END_BLOCKS_:
						{
							// arg[0] = whether within the END blocks section
							within_end_blocks = position.BoolArg(0);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._EXIT_WITH_CODE_:
						{
							// stack[0] = exit code
							exit_code = (int)org.jawk.jrt.JRT.ToDouble(Pop());
							if (!within_end_blocks)
							{
								//assert exit_address != null;
								// clear runtime stack
								runtime_stack.PopAllFrames();
								// clear operand stack
								operand_stack.Clear();
								position.Jump(exit_address);
							}
							else
							{
								// break;
								jrt.JrtCloseAll();
								// clear operand stack
								operand_stack.Clear();
								return exit_code;
							}
							//position.next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._REGEXP_:
						{
							// arg[0] = string representation of regexp
							string key = org.jawk.jrt.JRT.ToAwkString(position.Arg(0), GetCONVFMT().ToString(
								));

							System.Text.RegularExpressions.Regex pattern = null;
							if (!regexps.ContainsKey(key))
							{
                                regexps[key] = pattern = new System.Text.RegularExpressions.Regex(key);
							} else
							{
                                pattern = regexps[key];
							}
							Push(pattern);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._REGEXP_PAIR_:
						{
							// stack[0] = 1st regexp in pair
							// stack[1] = 2nd regexp in pair
                            org.jawk.jrt.PatternPair pp = null;
                            if(pattern_pairs.ContainsKey(position.Current()))
                            {
                                pp = pattern_pairs[position.Current()];
                            }
							if (pp == null)
							{
								string convfmt = GetCONVFMT().ToString();
								string s1 = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
								string s2 = org.jawk.jrt.JRT.ToAwkString(Pop(), convfmt);
								pattern_pairs[position.Current()] = pp = new org.jawk.jrt.PatternPair(s1, s2);
							}
							else
							{
								Pop();
								Pop();
							}
							Push(pp);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._IS_IN_:
						{
							// stack[0] = key to check
							// stack[1] = AssocArray
							object arg = Pop();
							object arr = Pop();
							org.jawk.jrt.AssocArray aa = (org.jawk.jrt.AssocArray)arr;
							bool result = aa.IsIn(arg);
							Push(result ? ONE : ZERO);
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CAST_DOUBLE_:
						{
							Push(org.jawk.jrt.JRT.ToDouble(Pop()));
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._CAST_STRING_:
						{
							Push(Pop().ToString());
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._THIS_:
						{
							// this is in preparation for a function
							// call for the JVM-COMPILED script, only
							// therefore, do NOTHING for the interpreted
							// version
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._EXEC_:
						{
							// stack[0] = Jawk code
							// First attempt.  It is not complete by a long-shot.
							// Use at your own risk.
							string awk_code = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
							org.jawk.frontend.AwkParser ap = new org.jawk.frontend.AwkParser(parameters.additional_functions
								, parameters.additional_type_functions, parameters.no_input, extensions);
							//true, true, true, extensions
							try
							{
								org.jawk.frontend.IAwkSyntaxTree ast = ap.Parse(new StringReader(awk_code));
								if (ast != null)
								{
									ast.SemanticAnalysis();
									ast.SemanticAnalysis();
									org.jawk.intermediate.AwkTuples new_tuples = new org.jawk.intermediate.AwkTuples(
										);
									int result = ast.PopulateTuples(new_tuples);
									//assert result == 0;
									new_tuples.PostProcess();
									ap.PopulateGlobalVariableNameToOffsetMappings(new_tuples);
									org.jawk.backend.AVM new_avm = new org.jawk.backend.AVM(parameters, extensions);
									int retcode = new_avm.Interpret(new_tuples);
									Push(retcode);
								}
								else
								{
									Push(-1);
								}
							}
							catch (System.IO.IOException ioe)
							{
								throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "IO Exception caught : "
									 + ioe);
							}
							position.Next();
							break;
						}

						case org.jawk.intermediate.AwkTuples._EXTENSION_:
						{
							// arg[0] = extension keyword
							// arg[1] = # of args on the stack
							// arg[2] = true if parent is NOT an extension function call
							// 		(i.e., initial extension in calling expression)
							// stack[0] = first actual parameter
							// stack[1] = second actual parameter
							// etc.
							string extension_keyword = position.Arg(0).ToString();
							int num_args = position.IntArg(1);
							bool is_initial = position.BoolArg(2);
							org.jawk.ext.IJawkExtension extension = null;
                            if(extensions.ContainsKey(extension_keyword))
                            {
                                extension = extensions[extension_keyword];
                            }
						    if (extension == null)
							{
								throw new org.jawk.jrt.AwkRuntimeException("Extension for '" + extension_keyword 
									+ "' not found.");
							}
							object[] args = new object[num_args];
							for (int i = 0; i < num_args; ++i)
							{
								args[i] = Pop();
							}
							object retval = extension.Invoke(extension_keyword, args);
							// block if necessary
							// (convert retval into the return value
							//  from the block operation ...)
							if (is_initial && retval != null && retval is org.jawk.jrt.BlockObject)
							{
								retval = new org.jawk.jrt.BlockManager().Block((org.jawk.jrt.BlockObject)retval);
							}
							// (... and proceed)
							if (retval == null)
							{
								retval = string.Empty;
							}
							else
							{
								if (retval is int)
								{
								}
								else
								{
									if (retval is double)
									{
									}
									else
									{
										if (retval is string)
										{
										}
										else
										{
											if (retval is org.jawk.jrt.AssocArray)
											{
											}
											else
											{
												if (retval is org.jawk.jrt.BlockObject)
												{
												}
												else
												{
													// pass a block object through...
													// all other extension results are converted
													// to a string (via Object.toString())
													retval = retval.ToString();
												}
											}
										}
									}
								}
							}
							Push(retval);
							position.Next();
							break;
						}

						default:
						{
							throw new System.Exception("invalid opcode: " + org.jawk.intermediate.AwkTuples.ToOpcodeString
								(position.Opcode()));
						}
					}
				}
				jrt.JrtCloseAll();
				//assert operand_stack.size() == 0 : "operand stack is NOT empty upon script termination.  operand_stack (size="+operand_stack.size()+") = "+operand_stack;
				return exit_code;
			}
			catch (System.Exception re)
			{
				System.Console.Out.WriteLine("Runtime Exception: " + re);
				System.Console.Out.WriteLine("operand_stack = " + operand_stack);
				System.Console.Out.WriteLine("position = " + position);
				System.Console.Out.WriteLine("line number = " + position.LineNumber());
				// clear runtime stack
				runtime_stack.PopAllFrames();
				// clear operand stack
				operand_stack.Clear();
				throw;
			}
			finally
			{
			}
		}

		//assert operand_stack.size() == 0 : "operand stack is NOT empty upon script termination.  operand_stack (size="+operand_stack.size()+") = "+operand_stack;
		// if (operand_stack.size() != 0)
		// 	throw new Error("operand stack is NOT empty upon script termination.  operand_stack (size="+operand_stack.size()+") = "+operand_stack);
		public virtual void WaitForIO()
		{
			jrt.JrtCloseAll();
		}

		private void AvmDump(org.jawk.jrt.AssocArray[] aa_array)
		{
			if (aa_array == null)
			{
				// dump the runtime stack
				object[] globals = runtime_stack.globals;
				foreach (string name in global_variable_offsets.Keys)
				{
					int idx = global_variable_offsets[name];
					object value = globals[idx];
					if (value is org.jawk.jrt.AssocArray)
					{
						org.jawk.jrt.AssocArray aa = (org.jawk.jrt.AssocArray)value;
						value = aa.MapString();
					}
					System.Console.Out.WriteLine(name + " = " + value);
				}
			}
			else
			{
				// dump associative arrays
				foreach (org.jawk.jrt.AssocArray aa in aa_array)
				{
					System.Console.Out.WriteLine(aa.MapString());
				}
			}
		}

		private void PrintTo(System.IO.TextWriter ps, int num_args)
		{
			// print items from the top of the stack
			// # of items
			if (num_args == 0)
			{
				// display $0
				ps.WriteLine(jrt.JrtGetInputField(0));
			}
			else
			{
				// cache $OFS to separate fields below
				// (no need to execute getOFS for each field)
				string ofs_string = GetOFS().ToString();
				for (int i = 0; i < num_args; i++)
				{
					string s = org.jawk.jrt.JRT.ToAwkStringForOutput(Pop(), GetOFMT().ToString());
					ps.Write(s);
					// if more elements, display $FS
					if (i < num_args - 1)
					{
						// use $OFS to separate fields
						ps.Write(ofs_string);
					}
				}
				ps.WriteLine();
			}
			// for now, since we are not using Process.waitFor()
			ps.Flush();
		}

		/// <param name="ps"></param>
		/// <param name="num_args">maxime</param>
		private void PrintfTo(System.IO.TextWriter ps, int num_args)
		{
			//assert num_args > 0;
            //
			ps.Write(SprintfFunction(num_args));
			// for now, since we are not using Process.waitFor()
				ps.Flush();
			
		}

		/// <summary>
		/// sprintf() functionality
		/// maxime
		/// </summary>
		private string SprintfFunction(int num_args)
		{
			//assert num_args > 0;
			// all but the format argument
			object[] arg_array = new object[num_args - 1];
			// the format argument!
			string fmt = org.jawk.jrt.JRT.ToAwkString(Pop(), GetCONVFMT().ToString());
			// for each sprintf argument, put it into an
			// array used in the String.format method
			for (int i = 0; i < num_args - 1; i++)
			{
				arg_array[i] = Pop();
			}
			if (trap_illegal_format_exceptions)
			{
				return org.jawk.jrt.JRT.SprintfFunction(arg_array, fmt);
			}
			else
			{
				return org.jawk.jrt.JRT.SprintfFunctionNoCatch(arg_array, fmt);
			}
		}

		private System.Text.StringBuilder replace_first_sb = new System.Text.StringBuilder
			();

		/// <summary>sub() functionality</summary>
		private string ReplaceFirst(string orig, string ere, string repl)
		{
			replace_first_sb.Length = 0;
			Push(org.jawk.jrt.JRT.ReplaceFirst(orig, repl, ere, replace_first_sb, GetCONVFMT(
				).ToString()));
			return replace_first_sb.ToString();
		}

		private System.Text.StringBuilder replace_all_sb = new System.Text.StringBuilder(
			);

		/// <summary>gsub() functionality</summary>
		private string ReplaceAll(string orig, string ere, string repl)
		{
			replace_all_sb.Length = 0;
			Push(org.jawk.jrt.JRT.ReplaceAll(orig, repl, ere, replace_all_sb, GetCONVFMT().ToString
				()));
			return replace_all_sb.ToString();
		}

		/// <summary>Awk variable assignment functionality.</summary>
		/// <remarks>Awk variable assignment functionality.</remarks>
		private void Assign(int offset, object value, bool is_global, org.jawk.intermediate.IPosition
			 position)
		{
			// check if curr value already refers to an array
			if (runtime_stack.GetVariable(offset, is_global) is org.jawk.jrt.AssocArray)
			{
				throw new org.jawk.jrt.AwkRuntimeException(position.LineNumber(), "cannot assign anything to an unindexed associative array"
					);
			}
			Push(value);
			runtime_stack.SetVariable(offset, value, is_global);
		}

		/// <summary>Awk array element assignment functionality.</summary>
		/// <remarks>
		/// Awk array element assignment functionality.
		/// maxime
		/// </remarks>
		private void AssignArray(int offset, object arr_idx, object rhs, bool is_global)
		{
			object o1 = runtime_stack.GetVariable(offset, is_global);
			if (o1 == null || (o1 is string) && o1.Equals(BLANK))
			{
				runtime_stack.SetVariable(offset, o1 = new org.jawk.jrt.AssocArray(sorted_array_keys
					), is_global);
			}
			//assert o1 != null;
			// The only (conceivable) way to contradict
			// the assertion (below) is by passing in
			// a scalar to an unindexed associative array
			// via a -v argument without safeguards to
			// prohibit this.
			// Therefore, guard against this elsewhere, not here.
			//if (! (o1 instanceof AssocArray))
			//	throw new AwkRuntimeException("Attempting to treat a scalar as an array.");
			//assert o1 instanceof AssocArray;
			org.jawk.jrt.AssocArray array = (org.jawk.jrt.AssocArray)o1;
			array.Put(arr_idx, rhs);
			Push(rhs);
		}

		/// <summary>
		/// Numerically increases an Awk variable by one; the result
		/// is placed back into that variable.
		/// </summary>
		/// <remarks>
		/// Numerically increases an Awk variable by one; the result
		/// is placed back into that variable.
		/// </remarks>
		private void Inc(int offset, bool is_global)
		{
			object o = runtime_stack.GetVariable(offset, is_global);
			if (o == null)
			{
				runtime_stack.SetVariable(offset, o = BLANK, is_global);
			}
			runtime_stack.SetVariable(offset, org.jawk.jrt.JRT.Inc(o), is_global);
		}

		/// <summary>
		/// Numerically decreases an Awk variable by one; the result
		/// is placed back into that variable.
		/// </summary>
		/// <remarks>
		/// Numerically decreases an Awk variable by one; the result
		/// is placed back into that variable.
		/// </remarks>
		private void Dec(int offset, bool is_global)
		{
			object o = runtime_stack.GetVariable(offset, is_global);
			if (o == null)
			{
				runtime_stack.SetVariable(offset, o = BLANK, is_global);
			}
			runtime_stack.SetVariable(offset, org.jawk.jrt.JRT.Dec(o), is_global);
		}

		/// <returns>
		/// The string value of the record separator.
		/// maxime
		/// </returns>
		public object GetRS()
		{
			//assert rs_offset != NULL_OFFSET;
			object rs_obj = runtime_stack.GetVariable(rs_offset, true);
			// true = global
			return rs_obj;
		}

		/// <returns>
		/// The string value of the output field separator.
		/// maxime
		/// </returns>
		public object GetOFS()
		{
			//assert ofs_offset != NULL_OFFSET;
			object ofs_obj = runtime_stack.GetVariable(ofs_offset, true);
			// true = global
			return ofs_obj;
		}

		/// <returns>
		/// The string value of the SUBSEP variable.
		/// maxime
		/// </returns>
		public object GetSUBSEP()
		{
			//assert subsep_offset != NULL_OFFSET;
			object subsep_obj = runtime_stack.GetVariable(subsep_offset, true);
			// true = global
			return subsep_obj;
		}

		/// <summary>Performs the global variable assignment within the runtime environment.</summary>
		/// <remarks>
		/// Performs the global variable assignment within the runtime environment.
		/// These assignments come from the ARGV list (bounded by ARGC), which, in
		/// turn, come from the command-line arguments passed into Awk.
		/// </remarks>
		/// <param name="name_value">
		/// The variable assignment in <i>name=value</i> form.
		/// maxime
		/// </param>
		/// <exception cref="System.ArgumentException"></exception>
		private void SetFilelistVariable(string name_value)
		{
			int eq_idx = name_value.IndexOf('=');
			// variable name should be non-blank
			//assert eq_idx >= 0;
			if (eq_idx == 0)
			{
				throw new System.ArgumentException("Must have a non-blank variable name in a name=value variable assignment argument."
					);
			}
            string name = name_value.Substring(0, eq_idx);
            string value = name_value.Substring(eq_idx + 1);
			object obj;
			try
			{
				obj = int.Parse(value);
			}
			catch (FormatException)
			{
				try
				{
                    obj = double.Parse(value, System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
				}
				catch (FormatException)
				{
					obj = value;
				}
			}
			// make sure we're not receiving funcname=value assignments
			if (function_names.Contains(name))
			{
				throw new System.ArgumentException("Cannot assign a scalar to a function name (" 
					+ name + ").");
			}
			if (global_variable_offsets.ContainsKey(name))
			{
                int offset_obj = global_variable_offsets[name];
                bool aarray_obj = global_variable_aarrays[name];
			
				//assert aarray_obj != null;
				if (aarray_obj)
				{
					throw new System.ArgumentException("Cannot assign a scalar to a non-scalar variable ("
						 + name + ").");
				}
				else
				{
					runtime_stack.SetFilelistVariable(offset_obj, obj);
				}
			}
		}

		// otherwise, do nothing
		public void AssignVariable(string name, object obj)
		{
			// make sure we're not receiving funcname=value assignments
			if (function_names.Contains(name))
			{
				throw new System.ArgumentException("Cannot assign a scalar to a function name (" 
					+ name + ").");
			}
			if (global_variable_offsets.ContainsKey(name))
			{
                int offset_obj = global_variable_offsets[name];
                bool aarray_obj = global_variable_aarrays[name];
            
				//assert aarray_obj != null;
				if (aarray_obj)
				{
					throw new System.ArgumentException("Cannot assign a scalar to a non-scalar variable ("
						 + name + ").");
				}
				else
				{
					runtime_stack.SetFilelistVariable(offset_obj, obj);
				}
			}
		}

		/// TODO: THROW AN ERROR HERE?!
		private void SwapOnStack()
		{
			object o1 = Pop();
			object o2 = Pop();
			Push(o1);
			Push(o2);
		}

		private void AvmConsumeInputForGetline()
		{
			try
			{
				if (AvmConsumeInput(true))
				{
					Push(1);
				}
				else
				{
					Push(string.Empty);
					Push(0);
				}
			}
			catch (System.IO.IOException)
			{
				Push(string.Empty);
				Push(-1);
			}
			SwapOnStack();
		}

		private void AvmConsumeFileInputForGetline(string filename)
		{
			try
			{
				if (AvmConsumeFileInput(filename))
				{
					Push(1);
				}
				else
				{
					Push(string.Empty);
					Push(0);
				}
			}
			catch (System.IO.IOException)
			{
				Push(string.Empty);
				Push(-1);
			}
			SwapOnStack();
		}

		private void AvmConsumeCommandInputForGetline(string cmd)
		{
			try
			{
				if (AvmConsumeCommandInput(cmd))
				{
					Push(1);
				}
				else
				{
					Push(string.Empty);
					Push(0);
				}
			}
			catch (System.IO.IOException)
			{
				Push(string.Empty);
				Push(-1);
			}
			SwapOnStack();
		}

		/// <exception cref="System.IO.IOException"></exception>
		private bool AvmConsumeFileInput(string filename)
		{
			bool retval = jrt.JrtConsumeFileInput(filename);
			if (retval)
			{
				Push(jrt.input_line);
			}
			return retval;
		}

		/// <exception cref="System.IO.IOException"></exception>
		private bool AvmConsumeCommandInput(string cmd)
		{
			bool retval = jrt.JrtConsumeCommandInput(cmd);
			if (retval)
			{
				Push(jrt.input_line);
			}
			return retval;
		}

		/// <exception cref="System.IO.IOException"></exception>
		private bool AvmConsumeInput(bool for_getline)
		{
			bool retval = jrt.JrtConsumeInput(for_getline);
			if (retval && for_getline)
			{
				Push(jrt.input_line);
			}
			return retval;
		}

		// private boolean avmConsumeInput(boolean for_getline) throws IOException
		// to satisfy the VariableManager interface
		public virtual object GetFS()
		{
			//assert fs_offset != NULL_OFFSET;
			object fs_string = runtime_stack.GetVariable(fs_offset, true);
			// true = global
			return fs_string;
		}

		public virtual object GetCONVFMT()
		{
			//assert convfmt_offset != NULL_OFFSET : "convfmt_offset not defined";
			object convfmt_string = runtime_stack.GetVariable(convfmt_offset, true);
			// true = global
			return convfmt_string;
		}

		public virtual void ResetFNR()
		{
			runtime_stack.SetVariable(fnr_offset, ZERO, true);
		}

		public virtual void IncFNR()
		{
			Inc(fnr_offset, true);
		}

		public virtual void IncNR()
		{
			Inc(nr_offset, true);
		}

		public virtual void SetNF(int I)
		{
			runtime_stack.SetVariable(nf_offset, I, true);
		}

		public virtual void SetFILENAME(string filename)
		{
			runtime_stack.SetVariable(filename_offset, filename, true);
		}

		public virtual object GetARGV()
		{
			return runtime_stack.GetVariable(argv_offset, true);
		}

		public virtual object GetARGC()
		{
			return runtime_stack.GetVariable(argc_offset, true);
		}

		private string GetOFMT()
		{
			//assert ofmt_offset != NULL_OFFSET;
			string ofmt_string = runtime_stack.GetVariable(ofmt_offset, true).ToString();
			// true = global
			return ofmt_string;
		}

		private static readonly string BLANK = string.Empty;

		/// <summary>The value of an address which is not yet assigned a tuple index.</summary>
		/// <remarks>The value of an address which is not yet assigned a tuple index.</remarks>
		public const int NULL_OFFSET = -1;

		private class RuntimeStack
		{
			public object[] globals = null;

			private object[] locals = null;

			private org.jawk.util.IMyStack<object[]> locals_stack = new org.jawk.util.ArrayStackImpl
				<object[]>();

			private org.jawk.util.IMyStack<int> return_indexes = new org.jawk.util.LinkedListStackImpl
				<int>();

			public virtual void Dump()
			{
                StringBuilder sGlobals = new StringBuilder("[");
			    foreach (object o in globals)
			    {
                    if(sGlobals.Length>1)
                    {
                        sGlobals.Append(", ");
                    }
                    sGlobals.Append(o.ToString());
			    }
                sGlobals.Append("]");

                StringBuilder sLocals = new StringBuilder("[");
                foreach (object o in locals)
                {
                    if (sLocals.Length > 1)
                    {
                        sLocals.Append(", ");
                    }
                    sLocals.Append(o.ToString());
                }
                sLocals.Append("]");

				System.Console.Out.WriteLine("globals = " + sGlobals);
				System.Console.Out.WriteLine("locals = " + sLocals);
				System.Console.Out.WriteLine("locals_stack = " + locals_stack);
				System.Console.Out.WriteLine("return_indexes = " + return_indexes);
			}

			/// <summary>Must be one of the first methods executed.</summary>
			/// <remarks>Must be one of the first methods executed.</remarks>
			internal virtual void SetNumGlobals(int num_globals)
			{
				//assert num_globals >= 0;
				//assert globals == null;
				globals = new object[num_globals];
			}

			// must accept multiple executions
			//expandFrameIfNecessary(num_globals);
			internal virtual object GetVariable(int offset, bool is_global)
			{
				//assert globals != null;
				//assert offset != NULL_OFFSET;
				if (is_global)
				{
					return globals[offset];
				}
				else
				{
					return locals[offset];
				}
			}

			internal virtual object SetVariable(int offset, object val, bool is_global)
			{
				//assert globals != null;
				//assert offset != NULL_OFFSET;
				if (is_global)
				{
					return globals[offset] = val;
				}
				else
				{
					return locals[offset] = val;
				}
			}

			// for _DELETE_ARRAY_
			internal virtual void RemoveVariable(int offset, bool is_global)
			{
				//assert globals != null;
				//assert offset != NULL_OFFSET;
				if (is_global)
				{
					//assert globals[offset] == null || globals[offset] instanceof AssocArray;
					globals[offset] = null;
				}
				else
				{
					//assert locals[offset] == null || locals[offset] instanceof AssocArray;
					locals[offset] = null;
				}
			}

			internal virtual void SetFilelistVariable(int offset, object value)
			{
				//assert globals != null;
				//assert offset != NULL_OFFSET;
				globals[offset] = value;
			}

			internal virtual void PushFrame(int num_fields, int position_idx)
			{
				locals_stack.Push(locals);
				locals = new object[num_fields];
				return_indexes.Push(position_idx);
			}

			/// <summary>returns the position index</summary>
			internal virtual int PopFrame()
			{
				locals = locals_stack.Pop();
				return return_indexes.Pop();
			}

			internal virtual void PopAllFrames()
			{
				int sz = locals_stack.Size();
				while (--sz >= 0)
				{
					locals = locals_stack.Pop();
					return_indexes.Pop();
				}
			}

			private object return_value;

			internal virtual void SetReturnValue(object obj)
			{
				//assert return_value == null;
				return_value = obj;
			}

			internal virtual object GetReturnValue()
			{
				object retval;
				if (return_value == null)
				{
					retval = BLANK;
				}
				else
				{
					retval = return_value;
				}
				return_value = null;
				return retval;
			}
			// private methods
		}
		// static class RuntimeStack
	}
}
